import core.ajax.Request;
import core.ui.Edit;
import core.ui.Dialog;
import core.ui.Static;
import core.ui.Password;
import core.ui.SplitWindow;
import core.util.Listeners;

import xcms.gui.DialogBuilder;
import xcms.plugins.auth.LoginFormValidator;

/**
 * Simple form with username/password fields.
 */
class xcms.plugins.auth.LoginForm extends core.ui.Dialog {

	/**
	 * Initializes the new login form.
	 */
	this.LoginForm = function() {
        this.listeners = new core.util.Listeners();
        with (core.ui) {
			super(null, '', '', 300, 155);

			this.setStyle('background-color', '#ffffff');
			this.setStyle('border', '1px solid #333333');

			var builder = new xcms.gui.DialogBuilder();
			var splitter = new SplitWindow(this, 0, 0, '100%', '100%');
			
			var form = new Window(splitter, 0, 0, '100%', 73);
			builder.createText(form, 'Username:', -180, 10);
			builder.createText(form, 'Password:', -180, 40);
			this.username = builder.createUsername(form, 130, 10);
			this.password = builder.createPassword(form, 130, 40);

			var message = new Window(splitter, 0, 0, '100%', 30);
			this.message = builder.createMessage(message, 20, 6);

			var buttons = new Window(splitter, 0, 0, '100%', 50);
			buttons.setStyle('border-top', '1px solid #333333');
			
			this.okButton = builder.createOkButton(buttons, this, -100, 15);
			this.cancelButton = builder.createCancelButton(buttons, this, -20, 15);
			
			splitter.addPane(form, SplitWindow.SPLIT_TOP);
			splitter.addPane(buttons, SplitWindow.SPLIT_BOTTOM);
			splitter.addPane(message, SplitWindow.SPLIT_BOTTOM);

			this.validator = new LoginFormValidator(this);
		}
	}

	/**
	 * Returns the username form field.
	 * @return Edit
	 */
	this.getUsername = function() {
		return this.username;
	}

	/**
	 * Returns the password form field.
	 * @return Password
	 */
	this.getPassword = function() {
		return this.password;
	}

	/**
	 * Adds a new form listener.
	 *
	 * @param listener (object) The listener to add.
	 */
	this.addFormListener = function(listener) {
		this.listeners.add(listener);
	}

	/**
	 * Removes the form listener.
	 *
	 * @param listener (object) The listener to remove.
	 */
	this.removeFormListener = function(listener) {
		this.listeners.remove(listener);
	}

	/**
	 * @see Window.setVisible
	 */
	this.setVisible = override(this.setVisible, function(visible) {
		super(visible);
		if (visible) {
			this.message.setText('');
			this.username.setFocus(true);
		}
	})

	/**
	 * @private
	 * Fires when user has completed the form.
	 */
	this.fireComplete = function() {
		this.listeners.call('onFormComplete', [ this ]);
	}

	/**
	 * @private
	 * Fires when user has cancelled the form.
	 */
	this.fireCancelled = function() {
		this.listeners.call('onFormCancelled', [ this ]);
	}

	/**
	 * Calls when user clicks OK or Cancel button.
	 *
	 * @param subject (Link) The link which is clicked.
	 */
	this.onActionPerformed = function(subject) {
		if (subject == this.okButton) {
			try {
				this.validator.validate();
				console.debug('Signing in as %s/%s', this.username.getText(), this.password.getText());
				this.message.setText('<span style="color: #333333">Please wait...</span>');
				var request = new core.ajax.Request('/cms/login/');
				request.addRequestListener(this);
				request.send({
					'username' : this.username.getText(),
					'password' : this.password.getText()
				});
			} catch (e) {	// ValidationError
				console.warn('Login form validation fails: %s', e.message);
				this.message.setText('<span style="color: #ff0000">' + e.getMessage() + '</span>');
			}
		} else {
			this.fireCancelled();
		}
	}

	/**
	 * Calls when AJAX request is completed.
	 *
	 * @param request (Request) The request obect.
	 * @param response (Response) The server response.
	 */
	this.onRequestComplete = function(request, response) {
		if ('OK' == response.status) {
			this.fireComplete();
		} else {
			console.warn('Login failed: %s', response.message);
			this.message.setText('<span style="color: #ff0000">' + response.message + '</span>');
		}
	}

	/**
	 * Calls when AJAX request is processed with error.
	 *
	 * @param request (Request) The request object.
	 * @param message (string) The error message.
	 */
	this.onRequestError = function(request, message) {
		console.error('Login failed: %s', message);
		// TODO: display error message?
		this.hide();
	}
}

/**
 * Returns the singleton instance of login form.
 * This method used to create login form on-demand.
 */
xcms.plugins.auth.LoginForm.getForm = function() {
	if (!defined(this.instance)) {
		this.instance = new LoginForm();
	}
	return this.instance;
}